﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MemoLib.Tasks;
using System.Configuration;
using System.Data;
using MemoLib.Operations;
using System.Timers;

namespace MemoLib
{
    public class TimeMother
    {
        public TimeMother() { }

        private static List<Task> GetAllTasks()
        {
            List<Task> ret = new List<Task>();
            ExcelOperator eop = new ExcelOperator(ConfigOperator.GetExcelPath());
            eop.OpenConn();
            DataTable dt1 = eop.GetTableFromExcelSheet("Sheet1");
            DataTable dt2 = eop.GetTableFromExcelSheet("Sheet2");
            eop.CloseConn();
            ret.AddRange(GetOnceTask(dt1));
            ret.AddRange(GetCycleTask(dt2));

            return ret;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dtOnce"></param>
        /// <returns></returns>
        private static List<Task> GetOnceTask(DataTable dtOnce)
        {
            List<Task> ret = new List<Task>();
            if (dtOnce != null && dtOnce.Rows.Count > 0)
            {
                foreach (DataRow row in dtOnce.Rows)
                {
                    DateTime? executeTime = UtilityConvert.ParseDateTime(row["最迟完成日期"]);
                    // 如果该任务还没有被执行,并且预计执行时间和当前时间之差不是大于间隔时间的情况就应该创建任务
                    // 过期但是为提醒的项目需要无条件提醒，马上就要提醒
                    if (executeTime != null && 
                        ((executeTime.Value - DateTime.Now).TotalMinutes <= ConfigOperator.GetIntervalMinutes() ||
                            executeTime.Value < DateTime.Now))
                    {
                        OnceTaskCard taskCard = new OnceTaskCard();
                        taskCard.CardID = Int64.Parse(row["ID"].ToString() as string);
                        taskCard.CreateDateTime = UtilityConvert.ParseDateTime(row["创建日期"]);
                        taskCard.ExecuteDateTime = executeTime.Value;
                        taskCard.ExecuteType = row["类型"] as string;
                        taskCard.Context = row["内容"] as string;
                        if (taskCard.ExecuteType.ToLower() == CommonData.OPERATIONTYPE_MESSAGE)
                        {
                            MessageOperation op = new MessageOperation();
                            op.Message = taskCard.Context;
                            taskCard.Operations.Add(op);
                        }
                        else
                        {
                            ExeAppOperation op = new ExeAppOperation();
                            op.AppPath = taskCard.Context;
                            taskCard.Operations.Add(op);
                        }

                        OnceTask task = new OnceTask();
                        task.Card = taskCard;


                        ret.Add(task);
                    }
                }
            }

            return ret;
        }

        private static List<Task> GetCycleTask(DataTable dtCycle)
        {
            List<Task> ret = new List<Task>();
            if (dtCycle != null && dtCycle.Rows.Count > 0)
            {
                foreach (DataRow row in dtCycle.Rows)
                {
                    CycleTask task = new CycleTask();

                    CycleTaskCard taskCard = new CycleTaskCard();
                    task.Card = taskCard;
                    taskCard.Frequency = (FrequencyType)Enum.Parse(typeof(FrequencyType), row["Frequency"].ToString());
                    taskCard.IfOnlyWorkday = Convert.ToString(row["IfOnlyWorkDay"]).ToLower() != "false"; // Empty and null means true
                    // 对于每天提醒的消息，如果设定了只是工作日提醒，那么周六和周日将不提醒。
                    if (taskCard.Frequency == FrequencyType.Day && taskCard.IfOnlyWorkday == true &&
                        (DateTime.Now.DayOfWeek == DayOfWeek.Saturday || DateTime.Now.DayOfWeek == DayOfWeek.Sunday))
                    {
                        continue;
                    }

                    taskCard.CardID = Int64.Parse(row["ID"].ToString());
                    // set the taskcard operation base on "type"
                    taskCard.ExecuteType = row["type"].ToString();
                    taskCard.Context = row["Context"].ToString();
                    if (taskCard.ExecuteType.ToLower() == "message")
                    {
                        MessageOperation op = new MessageOperation();
                        op.Message = taskCard.Context;
                        taskCard.Operations.Add(op);
                    }
                    else
                    {
                        ExeAppOperation op = new ExeAppOperation();
                        op.AppPath = taskCard.Context;
                        taskCard.Operations.Add(op);
                    }
                    
                    taskCard.Quantity = UtilityConvert.ParseInt(row["Quantity"]);
                    taskCard.Month = UtilityConvert.ParseInt(row["Month"]);
                    taskCard.Weekday = UtilityConvert.ParseInt(row["Weekday"]);
                    taskCard.Day = UtilityConvert.ParseInt(row["Day"]);
                    taskCard.Hour = UtilityConvert.ParseInt(row["Hour"]);
                    taskCard.Minute = UtilityConvert.ParseInt(row["Minute"]);
                    taskCard.ExecuteDateTime =DateTime.Parse(row["NextExecuteTime"].ToString());
                    
                    // 如果任务下次执行时间太早或者过期超过一个周期时间段，则不再放入
                    if (task.IsTooEarly() || task.IsOverdue())
                    {
                        continue;
                    }

                    ret.Add(task);
                }
            }
            
            return ret;
        }

        public static void Execute()
        {
            // 每一次执行之前都要将上下文清空
            ExecuteContext.Init();
            List<Task> lst = GetAllTasks();
           
            foreach (Task t in lst)
            {
                try
                {
                    t.Execute();
                }
                catch (Exception ex)
                {
                    Exception realEx = ex;
                    if(ex.InnerException != null)
                    {
                        realEx = ex.InnerException;
                    }
                    ExecuteContext.MessageBusket.Add("任务名称：" + t.Card.Note + Environment.NewLine + "异常信息:" + realEx.Message);
                }
            }
        }
    }
}
